import React, { PureComponent } from 'react';
import { formatMessage, FormattedMessage } from 'umi/locale';

import { connect } from 'dva';
import {
  Row,
  Col,
  Card,
  Form,
  Input,
  Select,
  Icon,
  Button,
  Dropdown,
  Menu,
  InputNumber,
  DatePicker,
  Modal,
  message,
  Badge,
  Divider,
  Steps,
  Radio,
  Tabs,
  Table,
  Upload,
  List,
  Avatar,
  Checkbox,
} from 'antd';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import DescriptionList from '@/components/DescriptionList';
import StandardTable from '@/components/StandardTable';
import MyIcon from '@/components/MyIcon';
import IconButton from '@/components/IconButton';
import styles from './BackApp.less';

const FormItem = Form.Item;
const InputGroup = Input.Group;
const Description = DescriptionList.Description;
const PROTOCOLS_RULE = {
  server_host: {
    pattern: /^[0-9.]+$/,
    message: '请输入数字和符号"."',
  },
  ftp_host: {
    pattern: /^[0-9.]+$/,
    message: '请输入数字和符号"."',
  },
  ftp_port: {
    pattern: /^[0-9]+$/,
    message: '请输入数字',
  },
  ssh_key: {
    pattern: /^[a-zA-Z0-9:]+$/,
    message: '请输入字母和数字和符号":"',
  },
};
let cardStyle = {
  bordered: false,
  headStyle: { border: 'none' },
  style: { width: '100%' },
};

@Form.create()
@connect(({ app, loading }) => ({
  actionLoading: loading.effects['app/createBackApp'] || loading.effects['app/updateBackApp'],
  app: app.app,
  backAppList: app.backAppList,
  protocols: app.protocols,
  appType: app.type,
}))
class BackApp extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      type: 'create',
      visible: false,
      selectedRowKeys: [],
      selectedRows: [],
      appDetail: {},
    };
  }

  componentDidMount() {
    this.queryApp();
    this.queryProtocols();
    this.queryTypes();
    this.queryBackAppList();
  }

  columns = [
    {
      title: formatMessage({ id: 'sysSet.Common.index' }),
      render: (text, record, index) => {
        return <span>{this.calcIndex(index)}</span>;
      },
    },
    {
      title: formatMessage({ id: 'sysSet.Common.code' }),
      dataIndex: 'code',
    },
    {
      title: formatMessage({ id: 'sysSet.Common.name' }),
      dataIndex: 'name',
    },
    {
      title: formatMessage({ id: 'sysSet.Common.protocolTypeName' }),
      dataIndex: 'protocolTypeName',
    },
    {
      title: formatMessage({ id: 'sysSet.Common.typeName' }),
      dataIndex: 'typeName',
    },
    {
      title: formatMessage({ id: 'sysSet.BackApp.BackApp.appTypeName' }),
      dataIndex: 'appTypeName',
    },
  ];

  calcIndex = index => {
    const { backAppList } = this.props;
    let currentPage = get(backAppList, 'pagination.currentPage') || 1;
    let pageSize = get(backAppList, 'pagination.pageSize') || 50;
    return (currentPage - 1) * pageSize + index + 1;
  };

  formatAppDetail = (data = {}) => {
    let appDetail = Object.create(null);
    if (data.application) {
      appDetail = {
        ...data.application,
        appCode: String(data.application.appCode),
        protocolType: String(data.application.protocolType),
      };
    }

    if (data.extension) {
      data.extension.forEach(item => {
        appDetail[item.keyName] = item.keyValue;
      });
    }
    return appDetail;
  };

  formatFieldsValue = (fieldsValue = {}) => {
    const { type, selectedRowKeys } = this.state;
    let params = Object.create(null);
    const protocol =
      this.props.protocols.find(item => item.code === fieldsValue.protocolType) || {};

    if (protocol.keys) {
      params.extension = protocol.keys.map(extension => {
        const params = {
          keyName: extension.code,
          keyValue: fieldsValue[extension.code],
        };

        type === 'edit' && (params.id = selectedRowKeys[0]);
        return params;
      });
    }

    params.application = {
      type: fieldsValue.type,
      appCode: fieldsValue.appCode,
      code: fieldsValue.code,
      description: fieldsValue.description,
      name: fieldsValue.name,
      protocolType: fieldsValue.protocolType,
    };

    type === 'edit' && (params.application.id = selectedRowKeys[0]);
    return params;
  };

  queryApp = () => {
    return this.props.dispatch({
      type: 'app/queryApp',
    });
  };

  queryProtocols = () => {
    return this.props.dispatch({
      type: 'app/queryProtocols',
    });
  };

  queryTypes = () => {
    return this.props.dispatch({
      type: 'app/queryTypes',
    });
  };

  queryAppDetail = () => {
    return this.props.dispatch({
      type: 'app/queryAppDetail',
      payload: {
        pathParams: {
          id: this.state.selectedRowKeys,
        },
      },
    });
  };

  queryBackAppList = ({ pageIndex = 1, pageSize = 50, ...params } = {}) => {
    const { dispatch, form } = this.props;
    form.validateFields((err, fieldsValue) => {
      let payload = {
        pageIndex: pageIndex,
        pageSize: pageSize,
        ...params,
      };
      if (fieldsValue.billTime && fieldsValue.billTime.length > 0) {
        payload.billStartTime = fieldsValue.billTime[0].format('YYYY-MM-DD');
        payload.billEndTime = fieldsValue.billTime[1].format('YYYY-MM-DD');
      }
      dispatch({
        type: 'app/queryBackAppList',
        payload: {
          queryParams: payload,
        },
      });
    });
  };

  createBackApp = params => {
    return this.props.dispatch({
      type: 'app/createBackApp',
      payload: {
        data: this.formatFieldsValue(params),
      },
    });
  };

  updateBackApp = params => {
    return this.props.dispatch({
      type: 'app/updateBackApp',
      payload: {
        data: this.formatFieldsValue(params),
      },
    });
  };

  deleteBackApp = () => {
    return this.props.dispatch({
      type: 'app/deleteBackApp',
      payload: {
        data: this.state.selectedRowKeys,
      },
    });
  };

  handleStandardTableChange = (pagination, filtersArg, sorter) => {
    const params = {
      pageIndex: pagination.current,
      pageSize: pagination.pageSize,
    };
    if (sorter.field) {
      params.sorter = `${sorter.field}_${sorter.order}`;
    }

    this.queryBackAppList(params);
    this.setState({
      selectedRowKeys: [],
      selectedRows: [],
    });
  };

  handleSelectChange = (selectedRowKeys, selectedRows) => {
    this.setState({ selectedRowKeys, selectedRows });
  };

  handleCreateClick = () => {
    this.props.form.resetFields();
    this.setState({
      type: 'create',
      visible: true,
      appDetail: {},
    });
  };

  handleEditClick = async () => {
    if (this.state.selectedRowKeys.length !== 1) {
      return;
    }
    const {
      form: { setFieldsValue, resetFields },
    } = this.props;
    resetFields();
    const res = await this.queryAppDetail();
    if (res.errorCode === 0) {
      this.setState({
        appDetail: this.formatAppDetail(res.data),
        type: 'edit',
        visible: true,
      });
    }
  };

  handleDeleteClick = () => {
    if (!this.state.selectedRowKeys || !this.state.selectedRowKeys.length) {
      return;
    }
    Modal.confirm({
      title: formatMessage({ id: 'sysSet.Common.delete' }),
      content: formatMessage({ id: 'sysSet.FrontApp.FrontApp.sureToDelete' }),
      confirmLoading: true,
      onOk: async () => {
        const res = await this.deleteBackApp();
        if (res.errorCode === 0) {
          this.queryBackAppList();
          this.setState({
            selectedRowKeys: [],
            selectedRows: [],
          });
          message.success(formatMessage({ id: 'sysSet.Common.deleteSuccess' }));
        }
      },
    });
  };

  handleModalOnOk = () => {
    const { form } = this.props;
    form.validateFields(async (err, values) => {
      if (err) {
        return;
      }
      const res = await (this.state.type === 'create'
        ? this.createBackApp(values)
        : this.updateBackApp(values));
      if (res.errorCode === 0) {
        message.success(formatMessage({ id: 'sysSet.Common.createSuccess' }));
        this.queryBackAppList();
        this.setState({
          visible: false,
        });
      }
    });
  };

  handleModalOnCancle = () => {
    this.setState({
      visible: false,
    });
  };

  renderModal = () => {
    const { visible, type, appDetail } = this.state;
    const {
      actionLoading,
      currency = [{ code: 'CNY', name: formatMessage({ id: 'sysSet.Common.CNY' }) }],
      app,
      appType,
      protocols,
      form: { getFieldDecorator, getFieldValue },
    } = this.props;
    return (
      <Modal
        confirmLoading={actionLoading}
        maskClosable={false}
        keyboard={false}
        destroyOnClose
        title={
          type === 'edit'
            ? formatMessage({ id: 'sysSet.Common.modify' })
            : formatMessage({ id: 'sysSet.Common.add' })
        }
        visible={visible}
        onOk={this.handleModalOnOk}
        onCancel={this.handleModalOnCancle}
      >
        <Form className={styles.backApp}>
          <FormItem label={formatMessage({ id: 'sysSet.BackApp.BackApp.appCode' })}>
            {getFieldDecorator('appCode', {
              rules: [
                {
                  required: true,
                  message: formatMessage({ id: 'sysSet.BackApp.BackApp.selectAppCode' }),
                },
              ],
              initialValue: appDetail.appCode,
            })(
              <Select placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.selectAppCode' })}>
                {app &&
                  Object.keys(app).map(key => (
                    <Option key={key} value={key}>
                      {app[key]}
                    </Option>
                  ))}
              </Select>
            )}
          </FormItem>
          <FormItem label={formatMessage({ id: 'sysSet.Common.code' })}>
            {getFieldDecorator('code', {
              normalize: value => {
                return value && value.replace(/\s/g, '');
              },
              rules: [
                {
                  required: true,
                  message: formatMessage({ id: 'sysSet.BackApp.BackApp.inputCode' }),
                },
                {
                  pattern: /^[\s\S]{0,16}$/,
                  message: formatMessage({ id: 'common.limitLengthTip' }, { limit: 16 }),
                },
              ],
              initialValue: appDetail.code,
            })(
              <Input
                // maxLength={16}
                placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.inputCode' })}
              />
            )}
          </FormItem>
          <FormItem label={formatMessage({ id: 'sysSet.Common.name' })}>
            {getFieldDecorator('name', {
              normalize: value => {
                return value && value.replace(/\s/g, '');
              },
              rules: [
                {
                  required: true,
                  message: formatMessage({ id: 'sysSet.BackApp.BackApp.inputName' }),
                },
                {
                  pattern: /^[\s\S]{0,16}$/,
                  message: formatMessage({ id: 'common.limitLengthTip' }, { limit: 16 }),
                },
              ],
              initialValue: appDetail.name,
            })(
              <Input
                // maxLength={16}
                placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.inputName' })}
              />
            )}
          </FormItem>
          <FormItem label={formatMessage({ id: 'sysSet.Common.protocolTypeName' })}>
            {getFieldDecorator('protocolType', {
              rules: [
                {
                  required: true,
                  message: formatMessage({ id: 'sysSet.BackApp.BackApp.selectProtocolType' }),
                },
              ],
              initialValue: appDetail.protocolType,
            })(
              <Select
                placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.selectProtocolType' })}
              >
                {protocols &&
                  protocols.map(({ code, name }) => (
                    <Option key={code} value={code}>
                      {name}
                    </Option>
                  ))}
              </Select>
            )}
          </FormItem>
          {getFieldValue('protocolType') &&
            (
              protocols.find(protocol => {
                return protocol.code === getFieldValue('protocolType');
              }) || { keys: [] }
            ).keys.map(key => {
              return (
                <FormItem label={key.name} key={key.code}>
                  {getFieldDecorator(`${key.code}`, {
                    normalize: value => {
                      return value && value.replace(/\s/g, '');
                    },
                    rules: [
                      {
                        required: true,
                        message: `请输入${key.name}`,
                      },
                      // {
                      //   ...PROTOCOLS_RULE[key.code],
                      // },
                    ],
                    initialValue: appDetail[key.code],
                  })(<Input maxLength={64} placeholder={`请输入${key.name}`} />)}
                </FormItem>
              );
            })}
          <FormItem label={formatMessage({ id: 'sysSet.Common.typeName' })}>
            {getFieldDecorator('type', {
              rules: [
                {
                  required: true,
                  message: formatMessage({ id: 'sysSet.BackApp.BackApp.selectType' }),
                },
              ],
              initialValue: appDetail.type ? appDetail.type + '' : undefined,
            })(
              <Select placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.selectType' })}>
                {appType &&
                  Object.keys(appType).map(key => (
                    <Option key={key} value={key}>
                      {appType[key]}
                    </Option>
                  ))}
              </Select>
            )}
          </FormItem>
          <FormItem label={formatMessage({ id: 'sysSet.Common.description' })}>
            {getFieldDecorator('description', {
              initialValue: appDetail.description,
              rules: [
                {
                  pattern: /^[\s\S]{0,64}$/,
                  message: formatMessage({ id: 'common.limitLengthTip' }, { limit: 64 }),
                },
              ],
            })(
              <Input.TextArea
                // maxLength={64}
                placeholder={formatMessage({ id: 'sysSet.BackApp.BackApp.inputDescription' })}
              />
            )}
          </FormItem>
        </Form>
      </Modal>
    );
  };

  renderTable = () => {
    const { loading, backAppList } = this.props;
    const { selectedRowKeys } = this.state;
    const rowSelection = {
      selectedRowKeys,
      onChange: this.handleSelectChange,
    };
    return (
      <StandardTable
        showCheckbox
        selectedRows={selectedRowKeys}
        rowSelection={rowSelection}
        rowKey="id"
        loading={loading}
        data={backAppList}
        columns={this.columns}
        onChange={this.handleStandardTableChange}
      />
    );
  };

  render() {
    return (
      <PageHeaderWrapper title={formatMessage({ id: 'sysSet.BackApp.BackApp.backApp' })}>
        <Card {...cardStyle} className={styles.cargoApply}>
          <div style={{ marginBottom: 20, height: '30px' }}>
            {
              <div>
                <IconButton
                  title={formatMessage({ id: 'sysSet.Common.add' })}
                  icon="icon-add"
                  onClick={this.handleCreateClick}
                  style={{ marginRight: '12px' }}
                />
                <IconButton
                  title={formatMessage({ id: 'sysSet.Common.modify' })}
                  icon="icon-edit"
                  onClick={this.handleEditClick}
                  style={{ marginRight: '12px' }}
                />
                <IconButton
                  title={formatMessage({ id: 'sysSet.Common.delete' })}
                  icon="icon-delete"
                  onClick={this.handleDeleteClick}
                />
              </div>
            }
          </div>
          {this.renderTable()}
        </Card>
        {this.renderModal()}
      </PageHeaderWrapper>
    );
  }
}

export default BackApp;
